import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:grint/utils/local_store.dart';
import 'dart:convert';

class FollowState {
  final Set<String> followingUserIds;
  final bool isLoading;
  final String? errorMessage;

  const FollowState({
    this.followingUserIds = const {},
    this.isLoading = false,
    this.errorMessage,
  });

  FollowState copyWith({
    Set<String>? followingUserIds,
    bool? isLoading,
    String? errorMessage,
  }) {
    return FollowState(
      followingUserIds: followingUserIds ?? this.followingUserIds,
      isLoading: isLoading ?? this.isLoading,
      errorMessage: errorMessage,
    );
  }

  bool isFollowing(String userId) {
    return followingUserIds.contains(userId);
  }
}

class FollowCubit extends Cubit<FollowState> {
  final LocalStore _localStore = LocalStore();
  static const String _followingKey = 'following_users';

  FollowCubit() : super(const FollowState()) {
    _loadFollowingUsers();
  }

  Future<void> _loadFollowingUsers() async {
    try {
      final followingJson = _localStore.getTextValue(
        _followingKey,
        defaultValue: '[]',
      );
      final List<dynamic> followingList = jsonDecode(followingJson);
      final followingUserIds = Set<String>.from(followingList);

      emit(state.copyWith(followingUserIds: followingUserIds));
    } catch (e) {
      emit(state.copyWith(errorMessage: 'Failed to load following users: $e'));
    }
  }

  Future<bool> followUser(String userId) async {
    if (state.isFollowing(userId)) {
      return true;
    }

    emit(state.copyWith(isLoading: true, errorMessage: null));

    try {
      final updatedFollowing = Set<String>.from(state.followingUserIds)
        ..add(userId);

      await _localStore.setTextValue(
        _followingKey,
        jsonEncode(updatedFollowing.toList()),
      );

      emit(
        state.copyWith(followingUserIds: updatedFollowing, isLoading: false),
      );

      return true;
    } catch (e) {
      emit(
        state.copyWith(
          isLoading: false,
          errorMessage: 'Failed to follow user: $e',
        ),
      );
      return false;
    }
  }

  Future<bool> unfollowUser(String userId) async {
    if (!state.isFollowing(userId)) {
      return true;
    }

    emit(state.copyWith(isLoading: true, errorMessage: null));

    try {
      final updatedFollowing = Set<String>.from(state.followingUserIds)
        ..remove(userId);

      await _localStore.setTextValue(
        _followingKey,
        jsonEncode(updatedFollowing.toList()),
      );

      emit(
        state.copyWith(followingUserIds: updatedFollowing, isLoading: false),
      );

      return true;
    } catch (e) {
      emit(
        state.copyWith(
          isLoading: false,
          errorMessage: 'Failed to unfollow user: $e',
        ),
      );
      return false;
    }
  }

  Future<bool> toggleFollow(String userId) async {
    if (state.isFollowing(userId)) {
      return await unfollowUser(userId);
    } else {
      return await followUser(userId);
    }
  }

  int getFollowingCount() {
    return state.followingUserIds.length;
  }

  Future<void> refreshFollowingUsers() async {
    await _loadFollowingUsers();
  }

  void clearError() {
    emit(state.copyWith(errorMessage: null));
  }
}
